package com.dao.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.dao.RelationDAO;
import com.model.Relation;
import com.model.User;
import com.util.Page;
import com.util.RelationType;

@Repository
public class RelationDAOImpl implements RelationDAO {

	@Autowired
	private SessionFactory sessionFactory;

	/**
	 * userId 关注 userById
	 * @param userId
	 * @param userById
	 * type==0 => userId 关注 userById
	 * type==1 => userById 关注 userId
	 * type==2 => userId 与 userById 相互关注
	 */
	@SuppressWarnings("unchecked")
	public String addAttention(int userId, int userById) {

		String hql = "From Relation r where r.userByUserId.id=:userId and r.userByUserById.id=:userById";
		Session s = sessionFactory.getCurrentSession();
		Query query = s.createQuery(hql);
		query.setInteger("userId", userId);
		query.setInteger("userById", userById);

		List<Relation> list = query.list();
		if (list.size() > 0) {
			Relation relation = list.get(0);
			if (relation.getType() == 0) {
				return "exist";
			}
			else if (relation.getType() == 1) {
				relation.setType(2);
				relation.setCreateAt(new Date());
				this.update(relation);
				return "success";
			}
			else if (relation.getType() == 2) {
				return "exist";
			}
		}
		query.setInteger("userId", userById);
		query.setInteger("userById", userId);
		list = query.list();
		if (list.size() > 0) {
			Relation relation = list.get(0);
			if (relation.getType() == 1) {
				return "exist";
			}
			else if (relation.getType() == 0) {
				relation.setType(2);
				relation.setCreateAt(new Date());
				this.update(relation);
				return "success";
			}
			else if (relation.getType() == 2) {
				return "exist";
			}
		}

		Relation r = new Relation();
		User u1 = new User();
		u1.setId(userId);
		User u2 = new User();
		u2.setId(userById);
		r.setUserByUserId(u1);
		r.setUserByUserById(u2);
		r.setType(0);
		r.setCreateAt(new Date());
		this.add(r);
		return "success";
	}

	/**
	 * userId 取消关注 userById
	 * @param userId
	 * @param byId
	 */
	@SuppressWarnings("unchecked")
	public String removeAttention(int userId, int userById) {

		String hql = "From Relation r where r.userByUserId.id=:userId and r.userByUserById.id=:userById";
		Session s = sessionFactory.getCurrentSession();
		Query query = s.createQuery(hql);
		query.setInteger("userId", userId);
		query.setInteger("userById", userById);

		List<Relation> list = query.list();
		if (list.size() > 0) {
			Relation relation = list.get(0);
			if (relation.getType() == 0) {
				this.delete(relation);
				return "success";
			}
			else if (relation.getType() == 2) {
				relation.setType(1);
				this.update(relation);
				return "success";
			}
			else {
				return "not exist";
			}
		}
		query.setInteger("userId", userById);
		query.setInteger("userById", userId);
		list = query.list();
		if (list.size() > 0) {
			Relation relation = list.get(0);
			if (relation.getType() == 1) {
				this.delete(relation);
				return "success";
			}
			else if (relation.getType() == 2) {
				relation.setType(0);
				this.update(relation);
				return "success";
			}
			else {
				return "not exist";
			}
		}
		return "not exist";
	}

	public void update(Relation relation) {
		sessionFactory.getCurrentSession().update(relation);
	}

	public void add(Relation relation) {
		sessionFactory.getCurrentSession().save(relation);
	}

	public void delete(Relation relation) {
		sessionFactory.getCurrentSession().delete(relation);
	}

	public void delete(int id) {
		Relation relation = (Relation) sessionFactory.getCurrentSession().load(Relation.class, id);
		sessionFactory.getCurrentSession().delete(relation);
	}

	public Page findUserAttentionForPage(int userId, int page, int pageSize) {
		//u.id as user_id,u.name as user_name,u.gender as user_gender,u.profession as user_profession,u.head_img as user_head,u.answers_num as user_answers_num,u.article_num as user_article_num,u.follow_num
		String sql = "select r.*,u.id as u_id,u.name as u_name,u.profession as u_profession,u.gender as u_gender,u.private_url as u_private_url,u.head_img as u_head_img,u.article_num as u_article_num,u.answers_num as u_answers_num,u.follow_num as u_follow_num,u.fans_num as u_fans_num,"
				+ "ub.id as ub_id,ub.name as ub_name,ub.profession as ub_profession,ub.gender as ub_gender,ub.private_url as ub_private_url,ub.head_img as ub_head_img,ub.article_num as ub_article_num,ub.answers_num as ub_answers_num,ub.follow_num as ub_follow_num,ub.fans_num as ub_fans_num "
				+ "from relation r inner join user u on u.id=r.user_id inner join user ub on ub.id=r.user_by_id where (r.user_id=:userId and (r.type=0 or r.type=2)) or (r.user_by_id=:userId and (r.type=1 or r.type=2)) order by r.create_at desc";

		String sqlc = "select count(*) from relation r where (r.user_id=:userId and (r.type=0 or r.type=2)) or (r.user_by_id=:userId and (r.type=1 or r.type=2))";

		Session s = sessionFactory.getCurrentSession();

		Query query = s.createSQLQuery(sql).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		Query queryc = s.createSQLQuery(sqlc);

		query.setInteger("userId", userId);
		queryc.setInteger("userId", userId);
		query.setMaxResults(pageSize);
		query.setFirstResult((page - 1) * pageSize);

		int count = Integer.parseInt((queryc.uniqueResult().toString()));
		List list = query.list();

		List<Map> users = new ArrayList<Map>();

		for (int i = 0; i < list.size(); i++) {
			Map map = (Map) list.get(i);
			int type = (Byte) map.get("type") & 0xFF;
			Map<String, Object> user = new HashMap<String, Object>();
			int uid = (Integer) map.get("u_id");
			if (uid != userId) {
				user.put("id", uid);
				user.put("name", map.get("u_name"));
				user.put("profession", map.get("u_profession"));
				user.put("gender", map.get("u_gender"));
				user.put("private_url", map.get("u_private_url"));
				user.put("head_img", map.get("u_head_img"));
				user.put("article_num", map.get("u_article_num"));
				user.put("answers_num", map.get("u_answers_num"));
				user.put("follow_num", map.get("u_follow_num"));
				user.put("fans_num", map.get("u_fans_num"));
				user.put("relation_type", type);
				users.add(user);
			}
			int ubid = (Integer) map.get("ub_id");
			if (ubid != userId) {
				user.put("id", ubid);
				user.put("name", map.get("ub_name"));
				user.put("profession", map.get("ub_profession"));
				user.put("gender", map.get("ub_gender"));
				user.put("private_url", map.get("ub_private_url"));
				user.put("head_img", map.get("ub_head_img"));
				user.put("article_num", map.get("ub_article_num"));
				user.put("answers_num", map.get("ub_answers_num"));
				user.put("follow_num", map.get("ub_follow_num"));
				user.put("fans_num", map.get("ub_fans_num"));
				user.put("relation_type", type);
				users.add(user);
			}

		}
		Page pageObj = new Page(count, pageSize, page);
		pageObj.setList(users);

		return pageObj;
	}

	public Page findAttensiondMeForPage(int userId, int page, int pageSize) {
		String sql = "select r.*,u.id as u_id,u.name as u_name,u.profession as u_profession,u.gender as u_gender,u.private_url as u_private_url,u.head_img as u_head_img,u.article_num as u_article_num,u.answers_num as u_answers_num,u.follow_num as u_follow_num,u.fans_num as u_fans_num,"
				+ "ub.id as ub_id,ub.name as ub_name,ub.profession as ub_profession,ub.gender as ub_gender,ub.private_url as ub_private_url,ub.head_img as ub_head_img,ub.article_num as ub_article_num,ub.answers_num as ub_answers_num,ub.follow_num as ub_follow_num,ub.fans_num as ub_fans_num "
				+ "from relation r inner join user u on u.id=r.user_id inner join user ub on ub.id=r.user_by_id where (r.user_id=:userId and (r.type=1 or r.type=2)) or (r.user_by_id=:userId and (r.type=0 or r.type=2)) order by r.create_at desc";

		String sqlc = "select count(*) from relation r where (r.user_id=:userId and (r.type=0 or r.type=2)) or (r.user_by_id=:userId and (r.type=1 or r.type=2))";

		Session s = sessionFactory.getCurrentSession();

		Query query = s.createSQLQuery(sql).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		Query queryc = s.createSQLQuery(sqlc);

		query.setInteger("userId", userId);
		queryc.setInteger("userId", userId);
		query.setMaxResults(pageSize);
		query.setFirstResult((page - 1) * pageSize);

		int count = Integer.parseInt((queryc.uniqueResult().toString()));
		List list = query.list();

		List<Map> users = new ArrayList<Map>();

		for (int i = 0; i < list.size(); i++) {
			Map map = (Map) list.get(i);
			int type = (Byte) map.get("type") & 0xFF;
			Map<String, Object> user = new HashMap<String, Object>();
			int uid = (Integer) map.get("u_id");
			if (uid != userId) {
				user.put("id", uid);
				user.put("name", map.get("u_name"));
				user.put("profession", map.get("u_profession"));
				user.put("gender", map.get("u_gender"));
				user.put("private_url", map.get("u_private_url"));
				user.put("head_img", map.get("u_head_img"));
				user.put("article_num", map.get("u_article_num"));
				user.put("answers_num", map.get("u_answers_num"));
				user.put("follow_num", map.get("u_follow_num"));
				user.put("fans_num", map.get("u_fans_num"));
				user.put("relation_type", type);
				users.add(user);
			}
			int ubid = (Integer) map.get("ub_id");
			if (ubid != userId) {
				user.put("id", ubid);
				user.put("name", map.get("ub_name"));
				user.put("profession", map.get("ub_profession"));
				user.put("gender", map.get("ub_gender"));
				user.put("private_url", map.get("ub_private_url"));
				user.put("head_img", map.get("ub_head_img"));
				user.put("article_num", map.get("ub_article_num"));
				user.put("answers_num", map.get("ub_answers_num"));
				user.put("follow_num", map.get("ub_follow_num"));
				user.put("fans_num", map.get("ub_fans_num"));
				user.put("relation_type", type);
				users.add(user);
			}

		}
		Page pageObj = new Page(count, pageSize, page);
		pageObj.setList(users);

		return pageObj;
	}

	public String findUserAttentionAsString(int userId) {
		try {
			//String hql = "From Relation r where (r.userByUserId.id=:userId and (r.type=0 or r.type=2)) or (r.userByUserById.id=:userId and (r.type=1 or r.type=2))";
			String sql = "select r.* from relation r where (r.user_id=:userId and (r.type=0 or r.type=2)) or (r.user_by_id=:userId and (r.type=1 or r.type=2))";
			Session s = sessionFactory.getCurrentSession();
			Query query = s.createSQLQuery(sql);
			query.setInteger("userId", userId);
			List list = query.list();

			StringBuffer uids = new StringBuffer();
			for (int i = 0; i < list.size(); i++) {
				Object[] objects = (Object[]) list.get(i);
				int uid = (Integer) objects[1];
				int ubyid = (Integer) objects[2];
				byte typeb = (Byte) objects[3];
				int type = typeb & 0xFF;

				if (uids.length() > 0)
					uids.append(",");
				if (type == 0)
					uids.append(ubyid);
				if (type == 1) {
					uids.append(uid);
				}
				if (type == 2) {
					if (uid == userId)
						uids.append(ubyid);
					else
						uids.append(uid);
				}

			}
			return uids.toString();
		}
		catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return null;
	}

	public int getUserRelation(int userId, int userById) {
		String hql = "From Relation r where r.userByUserId.id=:userId and r.userByUserById.id=:userById";
		Session s = sessionFactory.getCurrentSession();
		Query query = s.createQuery(hql);
		query.setInteger("userId", userId);
		query.setInteger("userById", userById);

		List<Relation> list = query.list();
		if (list.size() > 0) {
			Relation relation = list.get(0);
			if (relation.getType() == 0) {
				return RelationType.MYATTENSION;
			}
			else if (relation.getType() == 2) {
				return RelationType.EACH_ATTENSIONED;
			}
			else if(relation.getType() == 1){
				return RelationType.ATTENSIONEDME;
			}
		}
		query.setInteger("userId", userById);
		query.setInteger("userById", userId);
		list = query.list();
		if (list.size() > 0) {
			Relation relation = list.get(0);
			if (relation.getType() == 1) {
				return RelationType.MYATTENSION;
			}
			else if (relation.getType() == 2) {
				return RelationType.EACH_ATTENSIONED;
			}
			else if(relation.getType()==0){
				return RelationType.ATTENSIONEDME;
			}
		}
		return RelationType.NO_MATTER;
	}
	
	
}
